package com.example.mytestdemo.linearlayoutmanager

import android.content.Context
import android.util.Log
import android.view.View
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import android.view.View.MeasureSpec




/**
 * @author tgw
 * @date 2022/8/26
 * @describe
 *
 * 参考：https://blog.csdn.net/u011692041/article/details/76093920
 */
class MaxLineLinearLayoutManager : LinearLayoutManager {

    companion object{
        private const val TAG = "MaxLineLinearLayoutMana"
    }

    private var mMaxLine = 0

    constructor(
        context: Context?,
        maxLine: Int
    ) : super(context) {
//        Helper.checkMaxCount(maxLine)
        this.mMaxLine = maxLine
    }

    constructor(
        context: Context?,
        orientation: Int,
        reverseLayout: Boolean,
        maxLine: Int
    ) : super(context, orientation, reverseLayout) {
//        Helper.checkMaxCount(maxLine)
        this.mMaxLine = maxLine
    }

    override fun onMeasure(
        recycler: RecyclerView.Recycler,
        state: RecyclerView.State,
        widthSpec: Int,
        heightSpec: Int
    ) {
        Log.d(TAG, "tgw onMeasure itemCount: $itemCount")
        Log.d(TAG, "tgw onMeasure mMaxLine: $mMaxLine")

        if (itemCount <= mMaxLine || itemCount == 0) {
            super.onMeasure(recycler, state, widthSpec, heightSpec)
            return
        }

        val child = recycler.getViewForPosition(0)

        //
        addView(child)
        measureChild(child, 0, 0)
        //注意，这里getDecoratedMeasuredHeight计算的值，只有item确定了宽度，才得出正确的
        val itemWidth = getDecoratedMeasuredWidth(child)
        val itemHeight = getDecoratedMeasuredHeight(child)
        child.measuredHeight
        Log.d(TAG, "tgw onMeasure itemWidth: $itemWidth")
        Log.d(TAG, "tgw onMeasure itemHeight: $itemHeight")
        removeAndRecycleView(child, recycler)

        val widthMode = View.MeasureSpec.getMode(widthSpec)
        val heightMode = View.MeasureSpec.getMode(heightSpec)

        val widthModeSize = View.MeasureSpec.getSize(widthSpec)
        val heightModeSize = View.MeasureSpec.getSize(heightSpec)
        Log.d(TAG, "tgw onMeasure widthModeSize: $widthModeSize")
        Log.d(TAG, "tgw onMeasure heightModeSize: $heightModeSize")

        when (heightMode) {
            View.MeasureSpec.EXACTLY -> {
                Log.d(TAG, "tgw onMeasure heightMode: EXACTLY")
            }
            View.MeasureSpec.AT_MOST -> {
                Log.d(TAG, "tgw onMeasure heightMode: AT_MOST")

            }
            View.MeasureSpec.UNSPECIFIED -> {
                Log.d(TAG, "tgw onMeasure heightMode: UNSPECIFIED")
            }
        }

        when (widthMode) {
            View.MeasureSpec.EXACTLY -> {
                Log.d(TAG, "tgw onMeasure widthMode: EXACTLY")

            }
            View.MeasureSpec.AT_MOST -> {
                Log.d(TAG, "tgw onMeasure widthMode: AT_MOST")

            }
            View.MeasureSpec.UNSPECIFIED -> {
                Log.d(TAG, "tgw onMeasure widthMode: UNSPECIFIED")
            }
        }


        var width = 0
        var height = 0

        if (orientation == HORIZONTAL) {
            height = if (heightMode == View.MeasureSpec.EXACTLY) {
                View.MeasureSpec.getSize(heightSpec)
            } else {
                itemHeight
            }
            width = itemWidth * mMaxLine
        } else {
            width = if (widthMode == View.MeasureSpec.EXACTLY) {
                View.MeasureSpec.getSize(widthSpec)
            } else {
                itemWidth
            }
            height = itemHeight * mMaxLine
        }
        Log.d(TAG, "tgw onMeasure height: $height")
        Log.d(TAG, "tgw onMeasure width: $width")

        setMeasuredDimension(width, height)
    }

    override fun isAutoMeasureEnabled(): Boolean {
        if (itemCount <= mMaxLine) {
            return super.isAutoMeasureEnabled()
        }
        return false
    }


}


/*2、android:layout_width和android:layout_height设置为具体值时，那么是多少，宽高就是多少。
显然，默认的规则大部分不符合我们的需求，先来看下onMeasure()的参数，有两个参数，
widthMeasureSpec，heightMeasureSpec，以前不明白，我以为是View本身的大小，仔细想想也不对，
如果是本身的大小那还要你测什么啊，这两个参数是父布局给它提供的水平和垂直的空间要求，大家注意，
只是父布局提供的要求，当然View也可以不遵守在View的android:layout_width和android:layout_height的值就是onMeasure()
两个参数。什么意思，比如我为android:layout_width和android:layout_height设置的值为300dp，但是我在onMeasure()中，
测量时不遵守这个300dp的空间要求，将onMeasure()的实现改为：*/
fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
//    super.onMeasure(widthMeasureSpec, heightMeasureSpec)

    /*4)宽度、高度都是有测量模式和测量值的
     * 参数widthMeasureSpec与heightMeasureSpec都有两重含义
     * int mode = MeasureSpec.getMode(widthMeasureSpec)得到模式，
     * int size = MeasureSpec.getSize(widthMeasureSpec)得到尺寸。
     * mode总共有三种(测量模式)
     *
     */
    val specMode = MeasureSpec.getMode(widthMeasureSpec)
    val specSize = MeasureSpec.getSize(widthMeasureSpec)
    val specModeh = MeasureSpec.getMode(heightMeasureSpec)
    val specSizeh = MeasureSpec.getSize(heightMeasureSpec)
    //设置一个默认值，就是这个View的默认宽度为200，这个看我们自定义View的要求

/*  ①UNSPECIFIED：表示默认值，父控件没有给子view任何限制。------二进制表示：00

    ②EXACTLY：表示父控件给子view一个具体的值，子view要设置成这些值的大小。------二进制表示：01--
    具体的值(如width = 200dp) 和matchparent / fillparent

    ③AT_MOST：表示父控件个子view一个最大的特定值，而子view不能超过这个值的大小。------二进制表示：10
    包裹内容(width = wrapcontent) 则对应模式中的MeasureSpec.AT_MOST

    ③、AT_MOST(至多)，子元素最多达到指定大小的值。此时对应的布局参数的设置为：
    android:
    layout_width = "match_parent" android:
    layout_height = "match_parent"
    ②、EXACTLY(完全)，父控件决定子控件的的确切大小，子元素将被限定在给定的边界里而忽略它本身大小；
    此时对应的布局参数的设置为：android:
    layout_width = "100dp" android:
    layout_height = "100dp"
    父控件只给定了100dp的长宽供子控件布局*/

    /*widthSize = 200;
    if (specMode == MeasureSpec.AT_MOST) {////相当于我们设置为Wrap_content或者为一个具体的值
        widthSize =300;
    } else if (specMode == MeasureSpec.EXACTLY) {//相当于我们设置为match_parent或者为一个具体的值
        widthSize = specSize;
    }
    if (specModeh == MeasureSpec.AT_MOST) {
       heightSize = 300;
    } else if (specModeh == MeasureSpec.EXACTLY) {//相当于我们设置为match_parent或者为一个具体的值
        heightSize = specSizeh;
    }*/

//
//    widthSize = specSize
//    heightSize = specSizeh
//    setMeasuredDimension(widthSize, heightSize)

    //setMeasuredDimension 方法等同于super.onMeasure
//    val widthMeasureSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY)
//    val heightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY)
//
//    super.onMeasure(widthMeasureSpec, heightMeasureSpec)
}